﻿
using System.Security.AccessControl;
using System.Text;

internal class Util
{
    private static IDictionary<string, string> _nameMap = new Dictionary<string, string>();
    private static string Name(string name)
    {
        var sb = new StringBuilder();
        foreach (var c in name)
            if (c < 256)
                if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_')
                    sb.Append(c);
                else
                    sb.Append('_');
            else
                sb = sb.Append($"_uu{(int)(c):x2}");
        return sb.ToString();
    }
    internal static string ToFullName(string name)
    {
        if (_nameMap.TryGetValue(name, out var value))
            return value;
        var namespaces = name.Split('.');
        for (var i = 0; i < namespaces.Length; i++)
        {
            var names = namespaces[i].Split('/');
            for (var j = 0; j < names.Length; j++)
                names[j] = ToName(names[j].Trim());
            namespaces[i] = Join(".", names);
        }
        _nameMap[name] = value = Join('.', namespaces);
        return value;
    }
    internal static string ToNamespace(string name)
    {
        if (_nameMap.TryGetValue(name, out var value))
            return value;
        var names = name.Split('.');
        for (var i = 0; i < names.Length; i++)
            names[i] = ToName(names[i].Trim());
        _nameMap[name] = value = String.Join('.', names);
        return value;
    }
    internal static string ToLuaString(string name)
    {
        var sb = new StringBuilder();
        sb.Append('\'');
        for (var i = 0; i < name.Length; i++)
        {
            var c = name[i];
            switch (c)
            {
                case '\'':
                    sb.Append("\\'");
                    break;
                case '\\':
                    sb.Append("\\\\");
                    break;
                case '\r':
                    sb.Append("\\r");
                    break;
                case '\a':
                    sb.Append("\\a");
                    break;
                case '\b':
                    sb.Append("\\b");
                    break;
                case '\f':
                    sb.Append("\\f");
                    break;
                case '\n':
                    sb.Append("\\n");
                    break;
                case '\t':
                    sb.Append("\\t");
                    break;
                case '\v':
                    sb.Append("\\v");
                    break;
                default:
                    sb.Append(c);
                    break;
            }
        }
        sb.Append('\'');
        return sb.ToString();
    }
    internal static string ToName(string name)
    {
        if (!_nameMap.TryGetValue(name, out var newName))
        {
            _nameMap[name] = newName = Name(name);
        }
        return newName;
    }

    static string Generic(string value)
    {
    begin:
        var startIndex = value.IndexOf('<');
        var endIndex = value.IndexOf('>');
        if (startIndex >= 0 && endIndex >= 0)
        {
            value = value.Remove(startIndex, endIndex - startIndex);
            goto begin;
        }
        return value;
    }
    internal static string ToGenericFullName(string fullname)
    {
        return ToFullName(Generic(fullname));
    }
    internal static string ToGenericName(string name)
    {
        return ToName(Generic(name));
    }
}